<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>object oriented</title>
    <style type="text/css">
pre{
    /*font-family: "微软雅黑";*/
    font-size: 16px;
    line-height: 26px;
}


    </style>
</head>
<body>
    
<pre>
对象：不了解内部的结构，但对外提供了各种操作，类似于黑盒子
面向对象： 值关注对象提供的功能，不关注其内部细节，如jquery
面相对象是一种通用思想，并非只有编程中能用，任何事情都可以用



面相对象编程(OOP)的特点：
抽象：抓住核心问题
封装：不考虑内部实现，只考虑功能使用
继承：从已有对象上，继承出新的对象
      多重继承(会比较混乱)
      多态(适合强语言：java,c++; 弱语言：js 不太适用)



抽象：抽--把最主要的特征、跟问题相关的特征抽出来
封装：看不到里面的东西，用好表面的功能
继承：从父类上继承出一些方法和属性，子类又有一些自己的特性



对象的组成：
方法--函数：过程，动态的
属性--变量：状态，静态的



为对象添加方法和属性：
this详解，事件处理中this的本质
    window
    this--函数属于谁
不能在系统对象中随意附加方法、属性， 否则会覆盖已有方法、属性
object对象

this：当前发生事件的对象
      当前的方法属于谁




Date    日期
Array   数组
RegExp  正则
Object  几乎没有功能
在实现面相对象的时候，可以在Object上加属性和方法，可以最大限度和别人的方法或属性起冲突




CSS                                         JS
class      一次给一组元素加样式         原型--prototype
行间样式   一次给一个元素加样式         给对象加事件




类：  模子        --   用来生产
对象：产品(成品)  --   具有实际功能

var arr = new Array(1,2,3);
Array --  类
arr   --  对象


Array.push();    错误，Array是个模子，不具备实际功能，不能调用push
Array.prototype.sum    正确，在类上添加原型




</pre>




<script>

//---属性、方法-------------------------------------------------------------------------
// 变量：自由的，不属于任何人
var a = 13;  
// 函数：自由
function aaa(){    
    console.log("a~~");
}


var arr = [1,2,3,4,5,6];
// 属性：属于一个对象的
arr.a = 12;  
// 方法：属于一个对象
arr.aaa = function(){
    // this就是arr
    console.log(this.a);
}


console.log(a +"  "+ arr.a);
aaa();
arr.aaa();





//---new-------------------------------------------------------------------------
function show(){
    // alert(this);
}

show();      //[object Window]   this-->window
new show();  //[object Object]   this-->新new出来的对象





//---prototype-------------------------------------------------------------------------
var arr1 = new Array(12,55,34,78,676);
var arr2 = new Array(12,55,34,78,67);
var arr3 = new Array(12,55,34,78,68);

arr1.sum = function(){   //类似css中的行间样式
    var result = 0;
    for(var i=0; i<this.length; i++){
        result += this[i];
    }
    return result;
}
console.log(arr1.sum());
// console.log(arr2.sum());   //error
// console.log(arr3.sum());   //error



Array.prototype.sum = function(){   //类似css中的class
    var result = 0;
    for(var i=0; i<this.length; i++){
        result += this[i];
    }
    return result;
}
console.log(arr2.sum());
console.log(arr3.sum());





// ---call-------------------------------------------------------------------------
function showThis(a,b){
    console.log("This:" + this + ", a:" + a + ", b:" + b);
}
// 下面四句返回的都是Window
showThis();  
showThis.call();
window.showThis();
showThis.call(window);

showThis.call(12, "hello", "darling"); //This:12, a:hello, b:darling



//---1、创建对象-------------------------------------------------------------------------
var obj = new Object();
obj.name = 'kathy';
obj.qq = '258248832';
obj.showName = function(){
    console.log("My name is " + this.name);
}
obj.showQQ = function(){
    console.log("My qq is " + this.qq);
}
obj.showName();
obj.showQQ();




//---2、工厂模式：当需要创建很多个对象的时候------------------------------------------------------
// 缺点：
// 不能用new，用着不习惯
// 函数重复定义，资源浪费
// 没有解决对象识别的问题（怎样知道一个对象的类型）

function createPerson2(name, qq){  // 构造函数
    // 原料
    var obj = new Object();  

    // 加工
    obj.name = name;
    obj.qq = qq;
    obj.showName = function(){
        console.log("My name is " + this.name);
    }
    obj.showQQ = function(){
        console.log("My qq is " + this.qq);
    }

    // 出厂
    return obj;
}
var p21 = createPerson2("Rock", "45486452");
var p22 = createPerson2("Jack", "23477544");
p21.showName();
p22.showName();
console.log(p21.showName == p22.showName);      //false
console.log(p21.constructor == Object);         //true
console.log(p21.constructor == createPerson2);  //false



//---3、构造函数模式------------------------------------------------------

function createPerson3(name, qq){  // 构造函数
    // 系统偷偷地替咋们新建一个this空白对象:
    // var this = new Object(); 

    // 加工
    this.name = name;
    this.qq = qq;
    this.showName = function(){
        console.log("My name is " + this.name);
    }
    this.showQQ = function(){
        console.log("My qq is " + this.qq);
    }
    // 系统偷偷地替咋们把this返回:
    // return this;
}

// 1、当做构造函数使用--new
var p31 = new createPerson3("Hope", "123");
var p32 = new createPerson3("Frank", "789");
p31.showName();
p32.showName();
console.log(p31.constructor == Object);        //false
console.log(p31.constructor == createPerson3); //true

console.log(p31 instanceof Object);         //true
console.log(p31 instanceof createPerson3);  //true

// 2、作为普通函数调用--在全局作用域中调用一个函数，this对象总是指向Global对象
createPerson3("Ann", "567");
window.showName();


// 3、在另一个对象的作用域中调用--可以使用call(),apply()createPerson3()函数。这里是在p33的作用域中调用的，调用后p33就拥有了所有属性和showName()方法
var p33 = new Object();
createPerson3.call(p33, "Kate", "135");
p33.showName();







//---4、混合模式：构造 + 原型------------------------------------------------------

// 用构造函数加属性
function createPerson4(name, qq){
    this.name = name;
    this.qq = qq;
}
// 用原型加方法
createPerson4.prototype.showName = function(){
    console.log("4 My name is " + this.name);
}
createPerson4.prototype.showQQ = function(){
    console.log("4 My qq is " + this.qq);
}


var p41 = new createPerson4("Sally", "123");
var p42 = new createPerson4("Alice", "789");
p41.showName();
p42.showName();
console.log(p41.showName == p42.showName);  //true




//---5、用json实现的面向对象(单体)------------------------------------------------------------------------
// 优点：写法简单
// 缺点：不适合多个对象
var json = {
    name: "xuxuan",
    qq: "123456",
    showName: function(){
        console.log("my name is "+this.name);
    },
    showQQ: function(){
        console.log("my qq is "+this.qq);
    }
};

json.showName();
json.showQQ();





//---6、继承：问题------------------------------------------------------------------------
/*function A(){
    this.abc = 12;
}
A.prototype.show = function(){
    console.log(this.abc);
}


// B 继承 A
function B(){
    // 继承属性
    A.call(this);  // this -> new B()
}
// 继承原型，这样写有问题
B.prototype = A.prototype;
// B 新增的方法
B.prototype.sayB = function(){
    console.log("bbb");
}


var b = new B();
console.log(b.abc); //12
b.show();     //12
b.sayB();     //bbb


// 问题来了--A也能调用B的新加的sayB方法
var a = new A();
a.sayB();     //bbb*/




//---7、继承：修改------------------------------------------------------------------------
function A(){
    this.abc = 12;
}
A.prototype.show = function(){
    console.log(this.abc);
}

// 继承属性--call
function B(){
    A.call(this);
}
// 继承原型--for in，这样写就没有有问题
for(var i in A.prototype){
    B.prototype[i] = A.prototype[i];
}
// B 新增的方法
B.prototype.sayB = function(){
    console.log("bbb");
}


var b = new B();
console.log(b.abc); //12
b.show();     //12
b.sayB();     //bbb

// a不能调用B新增的方法
var a = new A();
//a.sayB();     //error:undefined is not a function






</script>
</body>
</html>